package com.zxy.fmmall.service.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import com.zxy.fmmall.dao.ProductImgMapper;
import com.zxy.fmmall.dao.ProductMapper;
import com.zxy.fmmall.dao.ProductParamsMapper;
import com.zxy.fmmall.dao.ProductSkuMapper;
import com.zxy.fmmall.entity.*;
import com.zxy.fmmall.service.ProductService;
import com.zxy.fmmall.utils.PageHelper;
import com.zxy.fmmall.vo.ResultVo;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.io.IOException;
import java.util.*;

@Service
public class ProductServiceImpl implements ProductService {
    @Autowired
    private ProductMapper productMapper;
    @Autowired
    private ProductImgMapper productImgMapper;
    @Autowired
    private ProductSkuMapper productSkuMapper;
    @Autowired
    private ProductParamsMapper productParamsMapper;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private Gson gson;
    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Override
    public ResultVo selectRecommendProducts() {
        List<Product> products = productMapper.selectRecommendProducts();
        return ResultVo.ok().data("products", products);
    }

    @Override
    public ResultVo selectBaseProducts(String productId) {
        try {
            String productInfo = (String) stringRedisTemplate.boundHashOps("product").get(productId);
            String productImgsInfo = (String) stringRedisTemplate.boundHashOps("productImgs").get(productId);
            String productSkusInfo = (String) stringRedisTemplate.boundHashOps("productSkus").get(productId);
            if (productInfo != null) {
//                HashMap<String, Object> map = new HashMap<>();
//                map.put("product",productInfo);
//                map.put("productImgs",productImgsInfo);
//                map.put("productSkus",productSkusInfo);
                Product product = objectMapper.readValue(productInfo, Product.class);
                JavaType javaType1 = objectMapper.getTypeFactory().constructParametricType(ArrayList.class, ProductImg.class);
                List<ProductImg> productImgs = objectMapper.readValue(productImgsInfo, javaType1);
                List<ProductSku> productSkus = gson.fromJson(productSkusInfo, new TypeToken<List<ProductSku>>() {
                }.getType());
                return ResultVo.ok().data("product", product).data("productImgs", productImgs).data("productSkus", productSkus);

            } else {
                Example example1 = new Example(Product.class);
                Example.Criteria criteria1 = example1.createCriteria();
                criteria1.andEqualTo("productId", productId);
                criteria1.andEqualTo("productStatus", 1);
                Product product = productMapper.selectOneByExample(example1);

                // 存到redis
                String productjsonStr = objectMapper.writeValueAsString(product);
                stringRedisTemplate.boundHashOps("product").put(productId, productjsonStr);


                if (product != null) {
                    Example example2 = new Example(ProductImg.class);
                    Example.Criteria criteria2 = example2.createCriteria();
                    criteria2.andEqualTo("itemId", productId);
                    List<ProductImg> productImgs = productImgMapper.selectByExample(example2);
                    // 存到redis
                    String productImgsjsonStr = objectMapper.writeValueAsString(productImgs);
                    stringRedisTemplate.boundHashOps("productImgs").put(productId, productImgsjsonStr);

                    Example example3 = new Example(ProductSku.class);
                    Example.Criteria criteria3 = example3.createCriteria();
                    criteria3.andEqualTo("productId", productId);
                    criteria3.andEqualTo("status", 1);
                    List<ProductSku> productSkus = productSkuMapper.selectByExample(example3);
                    // 存到redis
                    String productSkusjsonStr = objectMapper.writeValueAsString(productSkus);
                    stringRedisTemplate.boundHashOps("productSkus").put(productId, productSkusjsonStr);
                    return ResultVo.ok().data("product", product).data("productImgs", productImgs).data("productSkus", productSkus);
                }
                return ResultVo.error().message("商品不存在");
            }
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            return ResultVo.error();
        }
    }

    @Override
    public ResultVo getProductParamsById(String productId) {
        Example example = new Example(ProductParams.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("productId", productId);
        List<ProductParams> productParams = productParamsMapper.selectByExample(example);
        if (productParams.size() > 0) {
            return ResultVo.ok().data("productParams", productParams.get(0));
        } else {
            return ResultVo.error().message("可能为三无产品");
        }

    }

    @Override
    public ResultVo getProductsByCategoryId(int categoryId, int pageNum, int limit, String brand) {
        int start = (pageNum - 1) * limit;
        // 通过三级目录查询product
        List<Product> products = productMapper.selectProductByCategoryId(categoryId, start, limit, brand);

        // 查询总记录数
        List<Product> counts = productMapper.count(categoryId, brand);
        int count = counts.size();
        // 计算总页数
        int pageCount = count % limit == 0 ? count / limit : count / limit + 1;
        PageHelper<Product> pageHelper = new PageHelper<>(count, pageCount, products);
        return ResultVo.ok().data("pageHelper", pageHelper);
    }

    @Override
    public ResultVo getProductsByKeyword(String keyword, int pageNum, int limit) {
        ResultVo resultVo = null;
        try {
            // 查询搜索结果
            int start = (pageNum - 1) * limit;
            // 从ES查询数据
            SearchRequest request = new SearchRequest("fmmallproducts");
            // 查询条件
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            searchSourceBuilder.query(QueryBuilders.multiMatchQuery(keyword, "productName", "productSkuName"));

            //分页条件
            searchSourceBuilder.from(start);
            searchSourceBuilder.size(limit);
            // 高亮显示
            HighlightBuilder highlightBuilder = new HighlightBuilder();
            HighlightBuilder.Field productName = new HighlightBuilder.Field("productName");
            HighlightBuilder.Field productSkuName = new HighlightBuilder.Field("productSkuName");
            highlightBuilder.field(productName);
            highlightBuilder.field(productSkuName);
            highlightBuilder.preTags("<label style='color:red'>");
            highlightBuilder.postTags("</label>");
            // 高亮封装
            searchSourceBuilder.highlighter(highlightBuilder);
            // 查询封装
            request.source(searchSourceBuilder);

            //执行搜索
            SearchResponse searchResponse = restHighLevelClient.search(request, RequestOptions.DEFAULT);
            // 获取命中数据
            SearchHits hits = searchResponse.getHits();
            // 获取总记录数
            int count = (int) hits.getTotalHits().value;

            // mysql模糊查询
            //String kw = "%" + keyword + "%";
            //List<Product> products = productMapper.selectProductByKeyword(keyword, start, limit);
            // 查询总记录数
            //Example example = new Example(Product.class);
            //Example.Criteria criteria = example.createCriteria();
            //criteria.andLike("productName", kw);
            //int count = productMapper.selectCountByExample(example);

            //  计算总页数
            int pageCount = count % limit == 0 ? count / limit : count / limit + 1;

            Iterator<SearchHit> iterator = hits.iterator();
            // 封装查询结果
            ArrayList<ProductEs> products = new ArrayList<>();
            while (iterator.hasNext()){
                SearchHit searchHit = iterator.next();
                ProductEs productEs = objectMapper.readValue(searchHit.getSourceAsString(), ProductEs.class);
                // 获取高亮字段
                Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
                HighlightField field1 = highlightFields.get("productName");
                if (field1 != null){
                   String highLightProductName = Arrays.toString(field1.fragments());
                    productEs.setProductName(highLightProductName);
                }
                products.add(productEs);
            }
            // 封装返回数据
            PageHelper<Product> pageHelper = new PageHelper(count, pageCount, products);
            resultVo = ResultVo.ok().data("pageHelper", pageHelper);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return resultVo;
    }


}
